﻿// This code is released under the BSD license.
namespace PugLib
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using System.Globalization;

    [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
    public static class StrongEnum<T>
    {
        public static T Parse(string value)
        {
            return (T)Enum.Parse(typeof(T), value);
        }

        public static T Parse(string value, bool ignoreCase)
        {
            return (T)Enum.Parse(typeof(T), value, ignoreCase);
        }

        public static T ToObject(object value)
        {
            return (T)Enum.ToObject(typeof(T), value);
        }

        public static string GetName(object value)
        {
            return Enum.GetName(typeof(T), value);
        }

        public static string[] GetNames()
        {
            return Enum.GetNames(typeof(T));
        }

        public static IList<T> GetValues()
        {
            return Enum.GetValues(typeof(T)).OfType<T>().ToList();
        }

        public static bool IsDefined(object value)
        {
            return Enum.IsDefined(typeof(T), value);
        }

        public static Type GetUnderlyingType()
        {
            return Enum.GetUnderlyingType(typeof(T));
        }

        [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "1#")]
        public static string Format(object value, string format)
        {
            return Enum.Format(typeof(T), value, format);
        }

        [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "flag"),
         SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flag")]
        public static T AddFlag(T value, T flag)
        {
            int valueBase = Convert.ToInt32(value, CultureInfo.CurrentCulture);
            int flagBase = Convert.ToInt32(flag, CultureInfo.CurrentCulture);

            return ToObject(valueBase | flagBase);
        }

        [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "flag"),
         SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flag")]
        public static bool HasFlag(T value, T flag)
        {
            int valueBase = Convert.ToInt32(value, CultureInfo.CurrentCulture);
            int flagBase = Convert.ToInt32(flag, CultureInfo.CurrentCulture);

            return (valueBase & flagBase) == flagBase;
        }

        [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "flag"),
         SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flag")]
        public static T RemoveFlag(T value, T flag)
        {
            int valueBase = Convert.ToInt32(value, CultureInfo.CurrentCulture);
            int flagBase = Convert.ToInt32(flag, CultureInfo.CurrentCulture);

            return ToObject(valueBase & ~flagBase);
        }

        [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "flag"),
         SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flag")]
        public static T ToggleFlag(T value, T flag)
        {
            int valueBase = Convert.ToInt32(value, CultureInfo.CurrentCulture);
            int flagBase = Convert.ToInt32(flag, CultureInfo.CurrentCulture);

            return ToObject(valueBase ^ flagBase);
        }

        public static bool TryParse(string value, out T result)
        {
            result = default(T);

            try
            {
                result = Parse(value);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static bool TryParse(string value, bool ignoreCase, out T result)
        {
            result = default(T);

            try
            {
                result = Parse(value, ignoreCase);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}